home *** CD-ROM | disk | FTP | other *** search
/ QRZ! Ham Radio 4 / QRZ Ham Radio Callsign Database - Volume 4.iso / files / dsp / 56ktools / a5611.tz / a5611 / a56.y < prev    next >
Text File  |  1992-08-11  |  39KB  |  1,754 lines

  1. %{
  2. /*******************************************************
  3.  *
  4.  *  a56 - a DSP56001 assembler
  5.  *
  6.  *  Written by Quinn C. Jensen
  7.  *  July 1990
  8.  *  jensenq@npd.novell.com (or jensenq@qcj.icon.com)
  9.  *
  10.  *******************************************************\
  11.  
  12. /*
  13.  * Copyright (C) 1990-1992 Quinn C. Jensen
  14.  *
  15.  * Permission to use, copy, modify, distribute, and sell this software
  16.  * and its documentation for any purpose is hereby granted without fee,
  17.  * provided that the above copyright notice appear in all copies and
  18.  * that both that copyright notice and this permission notice appear
  19.  * in supporting documentation.  The author makes no representations
  20.  * about the suitability of this software for any purpose.  It is
  21.  * provided "as is" without express or implied warranty.
  22.  *
  23.  */
  24.  
  25. /*
  26.  *  a56.y - The YACC grammar for the assembler.
  27.  *
  28.  *  Note:  This module requires a "BIG" version of YACC.  I had to
  29.  *  recompile YACC in the largest mode available.
  30.  *
  31.  *  Other notes:
  32.  *
  33.  *  MOVEC, MOVEM and MOVEP must be used explicitly--MOVE can't yet figure
  34.  *  out which form to use.
  35.  *
  36.  */
  37.  
  38. #include "a56.h"
  39. unsigned int w0, w1, pc;
  40. extern BOOL list_on;
  41. BOOL uses_w1;
  42. int just_rep = 0;
  43. extern char inline[];
  44. char *spaces(), *luntab();
  45. char segs[] = "PXYL";
  46. int seg;
  47. int substatement = 0;
  48. BOOL long_symbolic_expr = FALSE;
  49.  
  50. struct n binary_op();
  51. struct n unary_op();
  52. struct n sym_ref();
  53.  
  54. #define R_R6            0x0001
  55. #define R_R5            0x0002
  56. #define R_R4            0x0004
  57. #define R_DATA_ALU_ACCUM    0x0008
  58. #define R_CTL_REG        0x0010
  59. #define R_FUNKY_CTL_REG        0x0020
  60. #define R_SDX            0x0040
  61. #define R_SDY            0x0080
  62. #define R_LSD            0x0100
  63. #define R_AB            0x0200
  64. #define R_XREG            0x0400
  65. #define R_YREG            0x0800
  66. /* registers to which short immediate move is an unsigned int */
  67. #define R_UINT            0x1000
  68. /* registers to which short immediate move is an signed frac */
  69. #define R_SFRAC            0x2000
  70. %}
  71.  
  72. %union {
  73.     int ival;    /* integer value */
  74.     struct n n;    /* just like in struct sym */
  75.     double dval;    /* floating point value */
  76.     char *sval;    /* string */
  77.     int cval;    /* character */
  78.     char cond;    /* condition */
  79.     struct regs {
  80.         int r6, r5, r4, data_alu_accum, ctl_reg, funky_ctl_reg;
  81.         int sdx, sdy, lsd, ab, xreg, yreg;
  82.         int flags;
  83.     } regs;
  84.     struct ea {
  85.         int mode;
  86.         int ext;
  87.         int pp;
  88.     } ea;
  89. }
  90.  
  91. %token <n> CHEX CDEC FRAC 
  92. %token <ival> AREG BREG MREG NREG RREG XREG YREG
  93. %token <ival> OP OPA OPP
  94. %token <cond> OP_JCC OP_JSCC OP_TCC
  95. %token <sval> SYM
  96. %token <sval> STRING
  97. %token <cval> CHAR
  98. %token COMMENT
  99. %token XMEM
  100. %token YMEM
  101. %token LMEM
  102. %token PMEM
  103. %token AAAA
  104. %token A10
  105. %token BBBB
  106. %token B10
  107. %token AABB
  108. %token BBAA
  109. %token XXXX
  110. %token YYYY
  111. %token SR
  112. %token MR
  113. %token CCR
  114. %token OMR
  115. %token SP
  116. %token SSH
  117. %token SSL
  118. %token LA
  119. %token LC
  120. %token EOL
  121. %token EOS
  122.  
  123. %token OP_ABS
  124. %token OP_ADC
  125. %token OP_ADD
  126. %token OP_ADDL
  127. %token OP_ADDR
  128. %token OP_ASL
  129. %token OP_ASR
  130. %token OP_CLR
  131. %token OP_CMP
  132. %token OP_CMPM
  133. %token OP_DIV
  134. %token OP_MAC
  135. %token OP_MACR
  136. %token OP_MPY
  137. %token OP_MPYR
  138. %token OP_NEG
  139. %token OP_NORM
  140. %token OP_RND
  141. %token OP_SBC
  142. %token OP_SUB
  143. %token OP_SUBL
  144. %token OP_SUBR
  145. %token OP_TFR
  146. %token OP_TST
  147. %token OP_AND
  148. %token OP_ANDI
  149. %token OP_EOR
  150. %token OP_LSL
  151. %token OP_LSR
  152. %token OP_NOT
  153. %token OP_OR
  154. %token OP_ORI
  155. %token OP_ROL
  156. %token OP_ROR
  157. %token OP_BCLR
  158. %token OP_BSET
  159. %token OP_BCHG
  160. %token OP_BTST
  161. %token OP_DO
  162. %token OP_ENDDO
  163. %token OP_LUA
  164. %token OP_MOVE
  165. %token OP_MOVEC
  166. %token OP_MOVEM
  167. %token OP_MOVEP
  168. %token OP_ILLEGAL
  169. %token OP_INCLUDE
  170. %token OP_JMP
  171. %token OP_JCLR
  172. %token OP_JSET
  173. %token OP_JSR
  174. %token OP_JSCLR
  175. %token OP_JSSET
  176. %token OP_NOP
  177. %token OP_REP
  178. %token OP_RESET
  179. %token OP_RTI
  180. %token OP_RTS
  181. %token OP_STOP
  182. %token OP_SWI
  183. %token OP_WAIT
  184. %token OP_EQU
  185. %token OP_ORG
  186. %token OP_DC
  187. %token OP_END
  188. %token OP_PAGE
  189. %token OP_PSECT
  190. %token OP_ALIGN
  191. %token SHL
  192. %token SHR
  193.  
  194. %type <n> num num_or_sym 
  195. %type <n> num_or_sym_expr
  196. %type <n> expr
  197. %type <n> ix
  198. %type <n> ix_long
  199.  
  200. %type <ival> abs_addr abs_short_addr io_short_addr 
  201. %type <ival> a_b x_or_y ea b5_10111_max
  202. %type <ival> p6_ean_a6 ea_no_ext p6_ea_a6 ea_a6 ea_a12
  203. %type <ival> ea_no_ext 
  204. %type <ival> ea_short
  205. %type <ival> prog_ctl_reg
  206. %type <ival> op8_1 op8_2 op8_3 op8_4 op8_5 op8_6 op8_7 op8_8
  207. %type <ival> mpy_arg mpy_srcs plus_minus
  208. %type <ival> sd3
  209. %type <ival> funky_ctl_reg tcc_sd space
  210.  
  211. %type <regs> regs
  212. %type <ea> movep_ea_pp
  213.  
  214. %left '|'
  215. %left '^'
  216. %left SHL SHR
  217. %left '&'
  218. %left '+' '-'
  219. %left '*' '/' '%'
  220. %right '~'
  221.  
  222. %start input
  223.  
  224. %%
  225.  
  226. /*%%%********************* top syntax ***********************/
  227.  
  228. input    :    /* empty */
  229.     |    input statement
  230.     ;
  231.  
  232. statement
  233.     :    good_stuff EOL
  234.             {substatement = 0;
  235.             if(NOT check_psect(seg, pc) && pass == 2)
  236.                 yyerror("%04X: psect violation", pc);
  237.             }
  238.     |    good_stuff EOS
  239.             {substatement++;
  240.             if(NOT check_psect(seg, pc) && pass == 2)
  241.                 yyerror("%04X: psect violation", pc);
  242.             }
  243.     |    error
  244.     ;
  245.  
  246. good_stuff
  247.     :    /* empty */
  248.             {if(pass == 2 && list_on) {
  249.                 printf("\n");
  250.             }}
  251.     |    cpp_droppings
  252.     |    COMMENT
  253.             {if(pass == 2 && NOT substatement && list_on) {
  254.                 printf("%s%s\n", spaces(0), luntab(inline));
  255.             }}
  256.     |    assembler_ops comment_field
  257.             {long_symbolic_expr = FALSE;}
  258.     |    label_field operation_field comment_field
  259.             {char *printcode();
  260.             if(pass == 2) {
  261.                 gencode(seg, pc, w0);
  262.                 if(list_on) printf("%c:%04X %s %s\n", segs[seg], pc, 
  263.                     printcode(w0), substatement ? "" :
  264.                         luntab(inline));
  265.                 pc++;
  266.                 if(uses_w1) {
  267.                     gencode(seg, pc, w1);
  268.                     if(list_on) printf("%c:%04X %s\n", segs[seg], pc,
  269.                                printcode(w1 & 0xFFFFFF));
  270.                     pc++;
  271.                 }
  272.             } else {
  273.                 pc++;
  274.                 if(uses_w1)
  275.                     pc++;
  276.             }
  277.             w0 = w1 = 0; uses_w1 = FALSE; 
  278.             long_symbolic_expr = FALSE;}
  279.     |    SYM comment_field
  280.             {sym_def($1, INT, pc);
  281.             free($1);
  282.             if(pass == 2) {
  283.                 if(list_on) printf("%c:%04X%s%s\n", segs[seg], pc, 
  284.                     spaces(14-8), substatement ? "" :
  285.                         luntab(inline));
  286.             long_symbolic_expr = FALSE;
  287.             }}
  288.     ;
  289.  
  290. cpp_droppings
  291.     :    '#' num STRING
  292.             {if(strlen($3) > 0)
  293.                 curfile = $3;
  294.             curline = $2.val.i - 2;}
  295.     ;
  296.  
  297. assembler_ops
  298.     :    SYM OP_EQU expr
  299.             {sym_def($1, $3.type, $3.val.i, $3.val.f);
  300.             free($1);
  301.             if(pass == 2 && list_on) {
  302.                 if($3.type == INT)
  303.                     printf("%06X%s",
  304.                         $3.val.i & 0xFFFFFF,
  305.                         spaces(14-6-2));
  306.                 else
  307.                     printf("%10g%s", $3.val.f,
  308.                         spaces(14-10-2));
  309.                 printf("%s\n", 
  310.                     substatement ? "" : luntab(inline));
  311.             }}
  312.     |    OP_ALIGN expr
  313.             {int ival = n2int($2);
  314.             if($2.type == UNDEF) {
  315.                 yyerror("illegal forward reference");
  316.             } else if (ival <= 1) {
  317.                 yyerror("%d: illegal alignment", ival);
  318.             } else {
  319.                 if(pc % ival != 0)
  320.                     pc += ival - pc % ival;
  321.             }
  322.             if(pass == 2 && list_on)
  323.                 printf("%c:%04X%s%s\n", segs[seg], pc, 
  324.                     spaces(14-8), substatement ? "" : luntab(inline));
  325.             }
  326.     |    OP_PSECT SYM
  327.             {struct psect *pp = find_psect($2);
  328.             if(NOT pp) {
  329.                 if(pass == 2)
  330.                     yyerror("%s: undefined psect", $2);
  331.             } else {
  332.                 seg = pp->seg;
  333.                 pc = pp->pc;
  334.                 set_psect(pp);
  335.                 if(pass == 2 && list_on) 
  336.                     printf("%c:%04X%s%s\n", segs[seg], pc, 
  337.                         spaces(14-8), substatement ? "" : luntab(inline));
  338.             }
  339.             free($2);}
  340.     |    OP_PSECT SYM space expr ':' expr
  341.             {new_psect($2, $3, n2int($4), n2int($6));
  342.             if(pass == 2 && list_on) 
  343.                 printf("%c:%04X %04X%s%s\n", 
  344.                     segs[$3], n2int($4), n2int($6), spaces(14-8+4+1), 
  345.                     substatement ? "" : luntab(inline));
  346.             }
  347.     |    OP_ORG space expr
  348.             {pc = n2int($3);
  349.             seg = $2;
  350.             if(pass == 2 && list_on) 
  351.                 printf("%c:%04X%s%s\n", segs[seg], pc, 
  352.                     spaces(14-8), substatement ? "" : luntab(inline));
  353.             }
  354.     |    OP_ORG space expr ',' space expr
  355.             {pc = n2int($3);
  356.             seg = $2;
  357.             if(pass == 2 && list_on)
  358.                 printf("%c:%04X%s%s\n", segs[seg], pc, 
  359.                     spaces(14-8), substatement ? "" : luntab(inline));
  360.             }
  361.     |    label_field OP_DC dc_list
  362.     |    OP_PAGE num ',' num ',' num ',' num
  363.             {if(pass == 2 && NOT substatement && list_on) {
  364.                 printf("%s%s\n", spaces(0), luntab(inline));
  365.             }}
  366.     |    OP_INCLUDE STRING
  367.             {if(pass == 2 && NOT substatement && list_on) {
  368.                 printf("%s%s\n", spaces(0), luntab(inline));
  369.             }
  370.             include($2); /* free($2); */
  371.             }
  372.     |    OP_END
  373.             {if(pass == 2 && NOT substatement && list_on) {
  374.                 printf("%s%s\n", spaces(0), luntab(inline));
  375.             }}
  376.     ;
  377.  
  378. dc_list
  379.     :    dc_list ',' dc_stuff
  380.     |    dc_stuff
  381.     ;
  382.  
  383. dc_stuff
  384.     :    STRING
  385.             {int len = strlen($1), i; char *cp; w0 = 0;
  386.             if(len % 3 == 2)
  387.                 len++;    /* force empty word */
  388.             for(i = 0, cp = $1; i < len; i++, cp++) {
  389.                 w0 |= (*cp & 0xFF) << (2 - (i % 3)) * 8;
  390.                 if(i % 3 == 2 || i == len - 1) {
  391.                     if(pass == 2) {
  392.                         if(list_on) printf("%c:%04X %06X%s%s\n",
  393.                             segs[seg], pc, w0, 
  394.                             spaces(14-6+5), 
  395.                             substatement ? "" : luntab(inline));
  396.                         gencode(seg, pc, w0);
  397.                         substatement++;
  398.                     }
  399.                     pc++; w0 = 0;
  400.                 }
  401.             }
  402.             free($1);}
  403.      |    expr
  404.             {int frac = n2frac($1);
  405.             if(pass == 2) {
  406.                 if(list_on) {
  407.                     printf("%c:%04X ", segs[seg], pc);
  408.                     printf("%06X%s", 
  409.                         frac & 0xFFFFFF,
  410.                             spaces(14-6+5));
  411.                     printf("%s\n",
  412.                         substatement ? "" : luntab(inline));
  413.                 }
  414.                 gencode(seg, pc, frac);
  415.                 substatement++;
  416.             }
  417.             pc++;}
  418.  
  419. space    :    PMEM
  420.             {$$ = PROG;}
  421.     |    XMEM
  422.             {$$ = XDATA;}
  423.     |    YMEM
  424.             {$$ = YDATA;}
  425.     |    LMEM
  426.             {$$ = LDATA;}
  427.     ;       
  428.  
  429. label_field
  430.     :    SYM
  431.             {sym_def($1, INT, pc);
  432.             free($1);}
  433.     |    /* empty */
  434.     ;
  435.  
  436. operation_field
  437.     :    operation
  438.             {if(just_rep) 
  439.                 just_rep--;}
  440.     ;
  441.  
  442. comment_field
  443.     :    COMMENT
  444.     |    /* empty */
  445.     ;
  446.  
  447. operation
  448.     :    no_parallel
  449.     |    parallel_ok
  450.             {w0 |= 0x200000;}
  451.     |    parallel_ok parallel_move
  452.     ;
  453.  
  454. /*%%%************* instructions that allow parallel moves ****************/
  455.  
  456. parallel_ok
  457.     :
  458.         OP_MPY mpy_arg
  459.             {w0 |= 0x80 | $2 << 2;}
  460.     |    OP_MPYR mpy_arg
  461.             {w0 |= 0x81 | $2 << 2;}
  462.     |    OP_MAC mpy_arg
  463.             {w0 |= 0x82 | $2 << 2;}
  464.     |    OP_MACR mpy_arg
  465.             {w0 |= 0x83 | $2 << 2;}
  466.  
  467.     |       OP_SUB op8_1
  468.             {w0 |= 0x04 | $2 << 3;}
  469.     |    OP_ADD op8_1
  470.             {w0 |= 0x00 | $2 << 3;}
  471.     |    OP_MOVE
  472.             {w0 |= 0x00;}
  473.  
  474.     |    OP_TFR op8_2
  475.             {w0 |= 0x01 | $2 << 3;}
  476.     |    OP_CMP op8_2
  477.             {w0 |= 0x05 | $2 << 3;}
  478.     |    OP_CMPM op8_2
  479.             {w0 |= 0x07 | $2 << 3;}
  480.  
  481.     |    OP_RND op8_3
  482.             {w0 |= 0x11 | $2 << 3;}
  483.     |    OP_ADDL op8_3
  484.             {w0 |= 0x12 | $2 << 3;}
  485.     |    OP_CLR op8_3
  486.             {w0 |= 0x13 | $2 << 3;}
  487.     |    OP_SUBL op8_3
  488.             {w0 |= 0x16 | $2 << 3;}
  489.     |    OP_NOT op8_3
  490.             {w0 |= 0x17 | $2 << 3;}
  491.  
  492.     |    OP_ADDR op8_4
  493.             {w0 |= 0x02 | $2 << 3;}
  494.     |    OP_TST op8_4
  495.             {w0 |= 0x03 | $2 << 3;}
  496.     |    OP_SUBR op8_4
  497.             {w0 |= 0x06 | $2 << 3;}
  498.  
  499.     |       OP_AND op8_5
  500.             {w0 |= 0x46 | $2 << 3;}
  501.     |    OP_OR op8_5
  502.             {w0 |= 0x42 | $2 << 3;}
  503.     |       OP_EOR op8_5
  504.             {w0 |= 0x43 | $2 << 3;}
  505.  
  506.     |       OP_ASR op8_6
  507.             {w0 |= 0x22 | $2 << 3;}
  508.     |       OP_LSR op8_6
  509.             {w0 |= 0x23 | $2 << 3;}
  510.     |       OP_ABS op8_6
  511.             {w0 |= 0x26 | $2 << 3;}
  512.     |       OP_ROR op8_6
  513.             {w0 |= 0x27 | $2 << 3;}
  514.  
  515.     |       OP_ASL op8_7
  516.             {w0 |= 0x32 | $2 << 3;}
  517.     |       OP_LSL op8_7
  518.             {w0 |= 0x33 | $2 << 3;}
  519.     |       OP_NEG op8_7
  520.             {w0 |= 0x36 | $2 << 3;}
  521.     |       OP_ROL op8_7
  522.             {w0 |= 0x37 | $2 << 3;}
  523.  
  524.     |       OP_ADC op8_8
  525.             {w0 |= 0x21 | $2 << 3;}
  526.     |       OP_SBC op8_8
  527.             {w0 |= 0x25 | $2 << 3;}
  528.     ;
  529.  
  530. mpy_arg    :    plus_minus mpy_srcs ',' a_b
  531.             {$$ = $1 | $4 << 1 | $2 << 2;}
  532.     ;
  533.  
  534. plus_minus
  535.     :    '+'    
  536.             {$$ = 0;}
  537.     |    '-'    
  538.             {$$ = 1;}
  539.     |    
  540.             {$$ = 0;}
  541.     ;
  542.  
  543. mpy_srcs
  544.     :       XREG ',' XREG
  545.             {switch ($1 << 4 | $3) {
  546.                 case 0x00: $$ = 0x0; break;
  547.                 case 0x01: 
  548.                 case 0x10: $$ = 0x2; break;
  549.                 case 0x11: 
  550.                     yyerror("illegal source operands"); 
  551.                     break;
  552.             }}                  
  553.     |    YREG ',' YREG
  554.             {switch ($1 << 4 | $3) {
  555.                 case 0x00: $$ = 0x1; break;
  556.                 case 0x01: 
  557.                 case 0x10: $$ = 0x3; break;
  558.                 case 0x11: 
  559.                     yyerror("illegal source operands"); 
  560.                     break;
  561.             }}                  
  562.     |    XREG ',' YREG
  563.             {switch ($1 << 4 | $3) {
  564.                 case 0x00: $$ = 0x5; break;
  565.                 case 0x01: $$ = 0x4; break;
  566.                 case 0x10: $$ = 0x6; break;
  567.                 case 0x11: $$ = 0x7; break;
  568.             }}                  
  569.     |    YREG ',' XREG
  570.             {switch ($1 << 4 | $3) {
  571.                 case 0x00: $$ = 0x5; break;
  572.                 case 0x01: $$ = 0x6; break;
  573.                 case 0x10: $$ = 0x4; break;
  574.                 case 0x11: $$ = 0x7; break;
  575.             }}                  
  576.     ;
  577.  
  578. op8_1    :    BBBB ',' AAAA
  579.             {$$ = 0x2;}
  580.     |    AAAA ',' BBBB
  581.             {$$ = 0x3;}
  582.     |    XXXX ',' a_b
  583.             {$$ = 0x4 | $3;}
  584.     |    YYYY ',' a_b
  585.             {$$ = 0x6 | $3;}
  586.     |    XREG ',' a_b
  587.             {$$ = 0x8 | $1 << 2 | $3;}
  588.     |    YREG ',' a_b
  589.             {$$ = 0xA | $1 << 2 | $3;}
  590.     ;
  591.  
  592. op8_2    :    BBBB ',' AAAA
  593.             {$$ = 0x0;}
  594.     |    AAAA ',' BBBB
  595.             {$$ = 0x1;}
  596.     |    XREG ',' a_b
  597.             {$$ = 0x8 | $1 << 2 | $3;}
  598.     |    YREG ',' a_b
  599.             {$$ = 0xA | $1 << 2 | $3;}
  600.     ;
  601.  
  602. op8_3    :    AAAA
  603.             {$$ = 0x0;}
  604.     |    BBBB
  605.             {$$ = 0x1;}
  606.     |    BBBB ',' AAAA
  607.             {$$ = 0x0;}
  608.     |    AAAA ',' BBBB
  609.             {$$ = 0x1;}
  610.     ;
  611.  
  612. op8_4    :    op8_3
  613.             {$$ = $1;}
  614.     ;
  615.  
  616. op8_5    :    XREG ',' a_b
  617.             {$$ = 0x0 | $1 << 2 | $3;}
  618.     |    YREG ',' a_b
  619.             {$$ = 0x2 | $1 << 2 | $3;}
  620.     ;
  621.  
  622. op8_6    :    a_b
  623.             {$$ = $1;}
  624.     ;
  625.  
  626. op8_7    :    a_b
  627.             {$$ = $1;}
  628.     ;
  629.  
  630. op8_8    :    XXXX ',' a_b
  631.             {$$ = 0x0 | $3;}
  632.     |    YYYY ',' a_b
  633.             {$$ = 0x2 | $3;}
  634.     ;
  635.  
  636. a_b    :    AAAA
  637.             {$$ = 0;}
  638.     |    BBBB
  639.             {$$ = 1;}
  640.     ;
  641.  
  642. no_parallel
  643.     :    control_inst
  644.             {if(just_rep == 1)
  645.                 yyerror("instruction not allowed after REP");}
  646.     |    bit_inst
  647.     |    move_inst
  648.     |    arith_inst
  649.     ;
  650.  
  651. /*%%%************** non-parallel arithmetic and logical ********************/
  652.  
  653. arith_inst
  654.     :    OP_NORM RREG ',' a_b
  655.             {w0 |= 0x01D815 | $2 << 8 | $4 << 3;}
  656.     |    OP_DIV sd3
  657.             {w0 |= 0x018040 | $2 << 3;}
  658.     |    or_op ix ',' funky_ctl_reg
  659.             {w0 |= 0x0000F8 | (n2int($2) & 0xFF) << 8 | $4;}
  660.     |    and_op ix ',' funky_ctl_reg
  661.             {w0 |= 0x0000B8 | (n2int($2) & 0xFF) << 8 | $4;}
  662.     ;
  663.  
  664. or_op    :    OP_OR
  665.     |    OP_ORI
  666.     ;
  667.  
  668. and_op    :    OP_AND
  669.     |    OP_ANDI
  670.     ;
  671.  
  672. /*%%%******************************* control instructions **********************/
  673.  
  674. control_inst
  675.     :    OP_JSCC ea_a12
  676.             {if($2) {
  677.                 w0 |= 0x0BC0A0 | $1 << 0;
  678.             } else {
  679.                 w0 |= 0x0F0000 | $1 << 12;
  680.             }}
  681.     |    OP_JCC ea_a12
  682.             {if($2) {
  683.                 w0 |= 0x0AC0A0 | $1 << 0;
  684.             } else {
  685.                 w0 |= 0x0E0000 | $1 << 12;
  686.             }}
  687.     |    OP_JSR ea_a12
  688.             {if($2) {
  689.                 w0 |= 0x0BC080;
  690.             } else {
  691.                 w0 |= 0x0D0000;
  692.             }}
  693.     |    OP_JMP ea_a12
  694.             {if($2) {
  695.                 w0 |= 0x0AC080;
  696.             } else {
  697.                 w0 |= 0x0C0000;
  698.             }}
  699.  
  700.     |    OP_JSSET control_args
  701.             {w0 |= 0x0B0020;}
  702.     |    OP_JSCLR control_args
  703.             {w0 |= 0x0B0000;}
  704.     |    OP_JSET control_args
  705.             {w0 |= 0x0A0020;}
  706.     |    OP_JCLR control_args
  707.             {w0 |= 0x0A0000;}
  708.  
  709.     |    OP_REP rep_args
  710.             {just_rep = 2;}
  711.     |    OP_DO do_args
  712.             {uses_w1++;}
  713.     |    OP_ENDDO
  714.             {w0 |= 0x00008C;}
  715.     |    OP_STOP
  716.             {w0 |= 0x000087;}
  717.     |    OP_WAIT
  718.             {w0 |= 0x000086;}
  719.     |    OP_RESET
  720.             {w0 |= 0x000084;}
  721.     |    OP_RTS
  722.             {w0 |= 0x00000C;}
  723.     |    OP_SWI
  724.             {w0 |= 0x000006;}
  725.     |    OP_ILLEGAL
  726.             {w0 |= 0x000005;}
  727.     |    OP_RTI
  728.             {w0 |= 0x000004;}
  729.     |    OP_NOP
  730.             {w0 |= 0x000000;
  731.             just_rep = 0;}
  732.     ;
  733.  
  734. do_args    :    ix ',' abs_addr
  735.             {int ival = n2int($1);
  736.             w0 |= 0x060080 | (ival & 0xFF) << 8 | (ival & 0xF00)>> 8;
  737.             if(ival > 0xFFF && pass == 2) {
  738.                 yyerror("warning: immediate operand truncated");
  739.             }
  740.             w1 |= $3-1;}
  741.     |    regs ',' abs_addr
  742.             {w0 |= 0x06C000 | $1.r6 << 8;
  743.             w1 |= $3-1;}
  744.     |    x_or_y ea_no_ext ',' abs_addr
  745.             {w0 |= 0x064000 | $2 << 8 | $1 << 6;
  746.             w1 |= $4-1;}
  747.     |    x_or_y abs_short_addr ',' abs_addr    /* allow forced */
  748.             {w0 |= 0x060000 | ($2 & 0x3F) << 8 | $1 << 6;
  749.             if($2 > 0x003F && pass == 2)
  750.                 yyerror("warning: address operand truncated");
  751.             w1 |= $4-1;}
  752.     |    x_or_y abs_addr ',' abs_addr
  753.             {w0 |= 0x060000 | ($2 & 0x3F) << 8 | $1 << 6;
  754.             if($2 > 0x003F && pass == 2)
  755.                 yyerror("warning: address operand truncated");
  756.             w1 |= $4-1;}
  757.     ;               
  758.  
  759. rep_args
  760.     :    ix
  761.             {int ival = n2int($1);
  762.             w0 |= 0x0600A0 | (ival & 0xFF) << 8 | (ival & 0xF00)>> 8;
  763.             if(ival > 0xFFF && pass == 2) {
  764.                 yyerror("warning: immediate operand truncated");
  765.             }}
  766.     |    regs
  767.             {w0 |= 0x06C020 | $1.r6 << 8;}
  768.     |    x_or_y ea_no_ext
  769.             {w0 |= 0x064020 | $1 << 6 | $2 << 8;}
  770.     |    x_or_y abs_addr
  771.             {w0 |= 0x060020 | $1 << 6 | ($2 & 0x3F) << 8;
  772.             if($2 > 0x003F && pass == 2)
  773.                 yyerror("warning: address operand truncated");
  774.             }
  775.     |    x_or_y abs_short_addr    /* forced */
  776.             {w0 |= 0x060020 | $1 << 6 | ($2 & 0x3F) << 8;
  777.             if($2 > 0x003F && pass == 2)
  778.                 yyerror("warning: address operand truncated");
  779.             }
  780.     ;
  781.  
  782. control_args
  783.     :    b5_10111_max ',' x_or_y p6_ean_a6 ',' abs_addr
  784.             {w0 |= $1 << 0 | $3 << 6;
  785.             uses_w1++;
  786.             w1 = $6;}
  787.     |    b5_10111_max ',' regs ',' abs_addr
  788.             {w0 |= 0x00C000 | $1 << 0 | $3.r6 << 8;
  789.             uses_w1++;
  790.             w1 = $5;}
  791.  
  792. p6_ean_a6
  793.     :    abs_addr    /* in pass 2 can always discern size. */
  794.                 /* Sometimes in pass one, too.  But since */
  795.                 /* address extension is always used for the */
  796.                 /* branch target, pass 1 can assume the */
  797.                 /* symbol value will fit; warning in pass 2 */
  798.                 /* if it doesn't */
  799.             {if($1 != -1) {    /* symbol defined */
  800.                 w0 |= ($1 & 0x3F) << 8;
  801.                 if($1 >= 0xFFC0) {
  802.                     w0 |= 0x008080;
  803.                 } else {
  804.                     w0 |= 0x000080;
  805.                     if($1 > 0x003F && pass == 2)
  806.                         yyerror("warning: address operand truncated");
  807.                 }
  808.             }}
  809.     |    abs_short_addr
  810.             {if($1 != -1) {
  811.                 if($1 > 0x3F && pass == 2)
  812.                     yyerror("warning: address operand truncated");
  813.                 w0 |= 0x000080 | ($1 & 0x3F) << 8;
  814.             }}
  815.     |    io_short_addr
  816.             {if($1 != -1) {
  817.                 if($1 < 0xFFC0 && pass == 2)
  818.                     yyerror("warning: address operand truncated");
  819.                 w0 |= 0x008080 | ($1 & 0x3F) << 8;
  820.             }}
  821.     |    ea_no_ext
  822.             {w0 |= 0x004080 | $1 << 8;}
  823.     ;
  824.  
  825. /*%%%**************************** bit instructions ***************************/
  826.  
  827. bit_inst
  828.     :    OP_BTST bit_args
  829.             {w0 |= 0x0B0020;}
  830.     |    OP_BCHG bit_args
  831.             {w0 |= 0x0B0000;}
  832.     |    OP_BSET bit_args
  833.             {w0 |= 0x0A0020;}
  834.     |    OP_BCLR bit_args
  835.             {w0 |= 0x0A0000;}
  836.     ;               
  837.  
  838. bit_args
  839.     :    b5_10111_max ',' x_or_y p6_ea_a6
  840.             {w0 |= $1 << 0 | $3 << 6;}
  841.     |    b5_10111_max ',' regs
  842.             {w0 |= 0x00C040 | $1 << 0 | $3.r6 << 8;}
  843.     ;           
  844.  
  845. p6_ea_a6
  846.     :    io_short_addr    /* must be forced to tell from abs_addr */
  847.             {if($1 != -1) {
  848.                 w0 |= ($1 & 0x3F) << 8 | 0x008000;
  849.                 if($1 < 0xFFC0 && pass == 2)
  850.                     yyerror("warning: address operand truncated");
  851.             }}
  852.     |    abs_short_addr    /* must be forced to tell from abs_addr */
  853.             {if($1 != -1) {
  854.                 w0 |= ($1 & 0x3F) << 8 | 0x000000;
  855.                 if($1 > 0x003F && pass == 2)
  856.                     yyerror("warning: address operand truncated");
  857.             }}
  858.     |    ea    /* can use abs_addr */
  859.             {w0 |= 0x004000;}
  860.     ;
  861.  
  862. /*%%%************************** move instructions **********************/
  863.  
  864. move_inst
  865.     :    OP_MOVEP movep_args
  866.     |    OP_MOVEM movem_args
  867.     |    OP_MOVEC movec_args
  868.     |    OP_LUA ea_short ',' regs
  869.             {w0 |= 0x044010 | $2 << 8 | $4.r4;}
  870.     |    OP_TCC tcc_args
  871.             {w0 |= $1 << 12;}
  872.     ;           
  873.  
  874. tcc_args
  875.     :    tcc_sd
  876.             {w0 |= 0x020000 | $1 << 3;}
  877.     |    tcc_sd RREG ',' RREG
  878.             {w0 |= 0x030000 | $1 << 3 | $2 << 8 | $4;}
  879.     ;
  880.  
  881. tcc_sd    :    regs /* a_b */ ',' regs /* a_b */
  882.             {if($1.flags & R_AB && $3.flags & R_AB) {
  883.                 if($1.ab == $3.ab) 
  884.                     yyerror("source and dest must be different");
  885.                 $$ = $3.ab;
  886.             } else if($1.flags & R_XREG && $3.flags & R_AB) {
  887.                 $$ = 0x8 | $1.xreg << 2 | $3.ab;
  888.             } else if($1.flags & R_YREG && $3.flags & R_AB) {
  889.                 $$ = 0xA | $1.yreg << 2 | $3.ab;
  890.             } else 
  891.                 yyerror("illegal TCC operands");
  892.             }
  893.     ;
  894.  
  895. sd3    :    regs /* XREG */ ',' regs /* a_b */
  896.             {if($1.flags & R_XREG && $3.flags & R_AB) {
  897.                 $$ = $1.xreg << 2 | $3.ab;
  898.             } else if($1.flags & R_YREG && $3.flags & R_AB) {
  899.                 $$ = $1.yreg << 2 | 2 | $3.ab;
  900.             }}
  901.     ;
  902.  
  903. movec_args
  904.     :    x_or_y ea ',' regs /* ctl_reg */
  905.             {if($1 == 0) {
  906.                 w0 |= 0x05C020 | $4.ctl_reg;
  907.             } else {
  908.                 w0 |= 0x05C060 | $4.ctl_reg;
  909.             }}
  910.     |    regs /* ctl_reg */ ',' x_or_y ea
  911.             {if($3 == 0) {
  912.                 w0 |= 0x054020 | $1.ctl_reg;
  913.             } else {
  914.                 w0 |= 0x054060 | $1.ctl_reg;
  915.             }}
  916.     |    ix ',' regs /* ctl_reg */
  917.             {int ival = n2int($1);
  918.             if(ival < 256 && NOT long_symbolic_expr) {
  919.                 w0 |= 0x0500A0 | (ival & 0xFF) << 8 | $3.ctl_reg; 
  920.             } else {
  921.                 w0 |= 0x05C020 | 0x003400 | $3.ctl_reg;
  922.                 uses_w1++; w1 = ival & 0xFFFF;
  923.             }}
  924.     |    x_or_y abs_short_addr ',' regs /* ctl_reg */
  925.             {if($1 == 0) {
  926.                 w0 |= 0x058020 | ($2 & 0x3F) << 8 | $4.ctl_reg;
  927.             } else {
  928.                 w0 |= 0x058060 | ($2 & 0x3F) << 8 | $4.ctl_reg;
  929.             }
  930.             if($2 > 0x003F && pass == 2)
  931.                 yyerror("warning: address operand truncated");
  932.             }
  933.     |    regs /* ctl_reg */ ',' x_or_y abs_short_addr
  934.             {if($3 == 0) {
  935.                 w0 |= 0x050020 | ($4 & 0x3F) << 8 | $1.ctl_reg;
  936.             } else {
  937.                 w0 |= 0x050060 | ($4 & 0x3F) << 8 | $1.ctl_reg;
  938.             }
  939.             if($4 > 0x003F && pass == 2)
  940.                 yyerror("warning: address operand truncated");
  941.             }
  942.     |    regs /* ctl_reg */ ',' regs
  943.             {if($1.flags & R_CTL_REG) {
  944.                 w0 |= 0x0440A0 | $3.r6 << 8 | $1.ctl_reg;
  945.             } else if($3.flags & R_CTL_REG) {
  946.                 w0 |= 0x04C0A0 | $1.r6 << 8 | $3.ctl_reg;
  947.             } else if($1.flags & $3.flags & R_CTL_REG) {
  948.                 /* bogus? $$$ */
  949.                        w0 |= 0x04C0A0 | ($1.ctl_reg | 0x20) << 8 | 
  950.                 $3.ctl_reg;
  951.             } else {
  952.                 yyerror("MOVEC must reference a control reg");
  953.             }}
  954.     ;
  955.  
  956. movep_args
  957.     :    x_or_y movep_ea_pp ',' x_or_y movep_ea_pp
  958.             {w0 |= 0x084080;
  959.             switch($2.pp << 1 | $5.pp) {
  960.                 case 0:    case 3:
  961.                     yyerror("illegal MOVEP; can't move EA to EA or IO to IO");
  962.                     break;
  963.                 case 1:    /* ea, pp */
  964.                     w0 |= $4 << 16 | 1 << 15 | $1 << 6 |
  965.                         ($5.ext & 0x3F);
  966.                     if($2.mode == 0x003000) {
  967.                         w0 |= 0x003000;
  968.                         uses_w1++;
  969.                         w1 = $2.ext;
  970.                     } else {
  971.                         w0 |= $2.mode;
  972.                     }
  973.                     break;
  974.                 case 2:    /* pp, ea */
  975.                     w0 |= $1 << 16 | 0 << 15 | $4 << 6 |
  976.                         ($2.ext & 0x3F);
  977.                     if($5.mode == 0x003000) {
  978.                         w0 |= 0x003000;
  979.                         uses_w1++;
  980.                         w1 = $5.ext;
  981.                     } else {
  982.                         w0 |= $5.mode;
  983.                     }
  984.                     break;
  985.             }}
  986.     |    ix ',' x_or_y num_or_sym
  987.             {w0 |= 0x084080;
  988.             w0 |= $3 << 16 | 1 << 15 | 0x34 << 8 | 
  989.                 (n2int($4) & 0x3F);
  990.             uses_w1++;
  991.             w1 = n2int($1);}
  992.     |    PMEM ea ',' x_or_y num_or_sym
  993.             {w0 |= 0x084040;
  994.             w0 |= $4 << 16 | 1 << 15 | (n2int($5) & 0x3F);}
  995.     |    x_or_y movep_ea_pp ',' PMEM ea
  996.             {w0 |= 0x084040;
  997.             if($2.mode != 0x003000 && $2.mode != 0)
  998.                 yyerror("illegal MOVEP");
  999.             w0 |= $1 << 16 | 0 << 15 | ($2.ext & 0x3F);}
  1000.     |    regs ',' x_or_y num_or_sym
  1001.             {w0 |= 0x084000;
  1002.             w0 |= $3 << 16 | 1 << 15 | $1.r6 << 8 | 
  1003.                 (n2int($4) & 0x3F);}
  1004.     |    x_or_y movep_ea_pp ',' regs
  1005.             {w0 |= 0x084000;
  1006.             if(!$2.pp)
  1007.                 yyerror("illegal MOVEP");
  1008.             w0 |= $1 << 16 | 0 << 15 | $4.r6 << 8 | ($2.ext & 0x3F);}
  1009.     ;
  1010.  
  1011. movep_ea_pp
  1012.     :    abs_addr
  1013.             {if($1 != UNDEF && $1 >= 0xFFC0) {
  1014.                 /* defined symbol or constant, in i/o range */
  1015.                 $$.pp = 1;
  1016.                 $$.mode = 0;
  1017.             } else {
  1018.                 /* either out of i/o range or symbol not */
  1019.                 /* yet defined:  assume ea extension */
  1020.                 $$.pp = 0;
  1021.                 $$.mode = 0x003000;
  1022.             }
  1023.             $$.ext = $1;}
  1024.     |    io_short_addr    /* forced i/o short */
  1025.             {$$.pp = 1;
  1026.             $$.mode = 0;
  1027.             if($1 < 0xFFC0 && pass == 2)
  1028.                 yyerror("warning: address operand truncated");
  1029.             $$.ext = $1;}
  1030.     |    ea_no_ext
  1031.             {$$.pp = 0;
  1032.             $$.mode = $1 << 8;
  1033.             $$.ext = $1;}
  1034.     ;
  1035.  
  1036. movem_args
  1037.     :    regs ',' PMEM ea_a6
  1038.             {w0 |= 0x070000 | 0 << 15 | $1.r6;}
  1039.     |    PMEM ea_a6 ',' regs
  1040.             {w0 |= 0x070000 | 1 << 15 | $4.r6;}
  1041.     ;
  1042.  
  1043. /*%%%**************** memory reference fields ************************/
  1044.  
  1045. b5_10111_max
  1046.     :    ix
  1047.             {int ival = n2int($1);
  1048.             $$ = ival; if(ival > 0x17) 
  1049.                 yyerror("%d: illegal bit number", ival);}
  1050.     ;
  1051.  
  1052. x_or_y    :    XMEM
  1053.             {$$ = 0;}
  1054.     |    YMEM
  1055.             {$$ = 1;}
  1056.     ;
  1057.  
  1058. /*%%%**************** effective address fields ************************/
  1059.  
  1060. ea_a6    :    ea
  1061.             {w0 |= 0x004080;}
  1062.     |    abs_short_addr
  1063.             {w0 |= ($1 & 0x3F) << 8;
  1064.             if($1 > 0x003F && pass == 2)
  1065.                 yyerror("warning: address operand truncated");
  1066.             }
  1067.     ;
  1068.  
  1069. ea_a12    :    ea
  1070.             {$$ = 1;}
  1071.     |    abs_short_addr
  1072.             {w0 |= $1 & 0xFFF; $$ = 0;
  1073.             if($1 > 0x0FFF && pass == 2)
  1074.                 yyerror("warning: address operand truncated");
  1075.             }
  1076.     ;
  1077.  
  1078. ea    :    abs_addr
  1079.             {w0 |= 0x003000;
  1080.             uses_w1++;
  1081.             w1 |= $1;
  1082.             $$ = 0x003000;}
  1083.     |    ea_no_ext
  1084.             {w0 |= $1 << 8;
  1085.             $$ = $1 << 8;}
  1086.     ;
  1087.  
  1088. ea_no_ext
  1089.     :    ea_short
  1090.             {$$ = $1;}
  1091.     |    '(' RREG ')'
  1092.             {$$ = 4 << 3 | $2;}
  1093.     |    '(' RREG '+' NREG ')'
  1094.             {$$ = 5 << 3 | $2;
  1095.             if($2 != $4) yyerror("Rn and Nn must be same number");}
  1096.     |    '-' '(' RREG ')'
  1097.             {$$ = 7 << 3 | $3;}
  1098.     ;
  1099.  
  1100. ea_short
  1101.     :    '(' RREG ')' '-' NREG
  1102.             {$$ = 0 << 3 | $2;
  1103.             if($2 != $5) yyerror("Rn and Nn must be same number");}
  1104.     |    '(' RREG ')' '+' NREG
  1105.             {$$ = 1 << 3 | $2;
  1106.             if($2 != $5) yyerror("Rn and Nn must be same number");}
  1107.     |    '(' RREG ')' '-'
  1108.             {$$ = 2 << 3 | $2;}
  1109.     |    '(' RREG ')' '+'
  1110.             {$$ = 3 << 3 | $2;}
  1111.     ;
  1112.  
  1113. /*%%%******************* register fields ******************************/
  1114.  
  1115. regs    :    XREG
  1116.             {$$.r6 = $$.r5 = 0x04 | $1;
  1117.             $$.sdx = $1;
  1118.             $$.xreg = $1;
  1119.             $$.flags = R_R6|R_R5|R_XREG|R_SDX|R_SFRAC;}
  1120.     |    YREG
  1121.             {$$.r6 = $$.r5 = 0x06 | $1;
  1122.             $$.sdy = $1;
  1123.             $$.yreg = $1;
  1124.             $$.flags = R_R6|R_R5|R_SDY|R_YREG|R_SFRAC;}
  1125.     |    AREG
  1126.             {switch($1) {
  1127.                 case 0: 
  1128.                     $$.r6 = $$.r5 = 0x08 | 0; 
  1129.                     break;
  1130.                 case 1: 
  1131.                     $$.r6 = $$.r5 = 0x08 | 4; 
  1132.                     break;
  1133.                 case 2: 
  1134.                     $$.r6 = $$.r5 = 0x08 | 2; 
  1135.                     break;
  1136.             }
  1137.             $$.flags = R_R6|R_R5|R_UINT;}
  1138.     |    BREG
  1139.             {switch($1) {
  1140.                 case 0: 
  1141.                     $$.r6 = $$.r5 = 0x08 | 1; break;
  1142.                 case 1: 
  1143.                     $$.r6 = $$.r5 = 0x08 | 5; break;
  1144.                 case 2: 
  1145.                     $$.r6 = $$.r5 = 0x08 | 3; break;
  1146.             }
  1147.             $$.flags = R_R6|R_R5|R_UINT;}
  1148.     |    AAAA
  1149.             {$$.r6 = $$.r5 = 0x0E;
  1150.             $$.sdx = $$.sdy = 0x2;
  1151.             $$.ab = 0;
  1152.             $$.lsd = 4;
  1153.             $$.flags = R_R6|R_R5|R_SDX|R_SDY|R_AB|R_LSD|R_SFRAC;}
  1154.     |    BBBB
  1155.             {$$.r6 = $$.r5 = 0x0F;
  1156.             $$.sdx = $$.sdy = 0x3;
  1157.             $$.ab = 1;
  1158.             $$.lsd = 5;
  1159.             $$.flags = R_R6|R_R5|R_SDX|R_SDY|R_AB|R_LSD|R_SFRAC;}
  1160.     |    RREG
  1161.             {$$.r6 = $$.r5 = 0x10 | $1;
  1162.             $$.r4 = 0x00 | $1;
  1163.             $$.flags = R_R6|R_R5|R_R4|R_UINT;}
  1164.     |    NREG
  1165.             {$$.r6 = $$.r5 = 0x18 | $1;
  1166.             $$.r4 = 0x08 | $1;
  1167.             $$.flags = R_R6|R_R5|R_R4|R_UINT;}
  1168.     |    MREG
  1169.             {$$.r6 = 0x20 | $1;
  1170.             $$.r5 = -1;
  1171.             $$.ctl_reg = $1;
  1172.             $$.flags = R_R6|R_R5|R_CTL_REG|R_UINT;}
  1173.     |    prog_ctl_reg
  1174.             {$$.r6 = 0x38 | $1;
  1175.             $$.r5 = -1;
  1176.             $$.ctl_reg = 0x18 | $1;
  1177.             $$.flags = R_R6|R_R5|R_CTL_REG|R_UINT;}
  1178.     |    A10
  1179.             {$$.lsd  = 0;
  1180.             $$.flags = R_LSD;}
  1181.     |    B10
  1182.             {$$.lsd = 1;
  1183.             $$.flags = R_LSD;}
  1184.     |    XXXX
  1185.             {$$.lsd = 2;
  1186.             $$.flags = R_LSD;}
  1187.     |    YYYY
  1188.             {$$.lsd = 3;
  1189.             $$.flags = R_LSD;}
  1190.     |    AABB
  1191.             {$$.lsd = 6;
  1192.             $$.flags = R_LSD;}
  1193.     |    BBAA
  1194.             {$$.lsd = 7;
  1195.             $$.flags = R_LSD;}
  1196.     ;
  1197.  
  1198. prog_ctl_reg
  1199.     :    SR
  1200.             {$$ = 1;}
  1201.     |    OMR
  1202.             {$$ = 2;}
  1203.     |    SP
  1204.             {$$ = 3;}
  1205.     |    SSH
  1206.             {$$ = 4;}
  1207.     |    SSL
  1208.             {$$ = 5;}
  1209.     |    LA
  1210.             {$$ = 6;}
  1211.     |    LC
  1212.             {$$ = 7;}
  1213.     ;
  1214.  
  1215. funky_ctl_reg
  1216.     :    MR
  1217.             {$$ = 0;}
  1218.     |    CCR
  1219.             {$$ = 1;}
  1220.     |    OMR
  1221.             {$$ = 2;}
  1222.     ;
  1223.  
  1224. /*%%%************************* parallel moves *************/
  1225.  
  1226. parallel_move
  1227.     :    i_move
  1228.     |    u_move
  1229.     |    x_or_y_move
  1230.     |    xr_move
  1231.     |    ry_move
  1232.     |    r_move
  1233.     |    xy_move
  1234.     |    l_move
  1235.     ;
  1236.  
  1237. i_move  :    ix ',' regs
  1238.             {int ival = n2int($1);
  1239.             int frac = n2frac($1);
  1240.             int value;
  1241.             BOOL shortform = FALSE;
  1242.             if($3.flags & R_CTL_REG) {
  1243.                 yyerror("please use MOVEC for control register moves");
  1244.                 break;
  1245.             }
  1246.             if($3.flags & R_SFRAC && $1.type == FLT) {
  1247.                 if((frac & 0xFFFF) == 0 && 
  1248.                     NOT long_symbolic_expr) {
  1249.                     value = frac >> 16;
  1250.                     shortform++;
  1251.                 } else {
  1252.                     value = frac;
  1253.                 }
  1254.             } else {
  1255.                 if(ival <= 0xFF && NOT long_symbolic_expr) {
  1256.                     value = ival;
  1257.                     shortform++;
  1258.                 } else {
  1259.                     value = ival;
  1260.                 }
  1261.             }
  1262.  
  1263.             if(shortform) {
  1264.                 w0 |= 0x200000 | (value & 0xFF) << 8 |
  1265.                     $3.r5 << 16;
  1266.             } else {
  1267.                 w0 |= 0x400000 | 0x00F400 |
  1268.                     ($3.r5 >> 3 & 3) << 20 | 
  1269.                     ($3.r5 & 7) << 16;
  1270.                 uses_w1++; w1 = value;
  1271.             }}
  1272.     ;
  1273.  
  1274. r_move    :    regs ',' regs
  1275.             {
  1276.                 if($3.flags & R_CTL_REG) {
  1277.                     yyerror("please use MOVEC for control register moves");
  1278.                     break;
  1279.                 }
  1280.                 if($1.flags & R_R5 & $3.flags) 
  1281.                     w0 |= 0x200000 | $3.r5 << 8 | $1.r5 << 13;
  1282.                 else
  1283.                     yyerror("illegal R move");
  1284.             }    
  1285.     ;
  1286.  
  1287. u_move    :    ea_short
  1288.             {w0 |= 0x204000 | $1 << 8;}
  1289.     ;
  1290.  
  1291. x_or_y_move
  1292.     :    x_or_y ea ',' regs
  1293.             {w0 |= 0x40C000 | $1 << 19;
  1294.             if($4.flags & R_CTL_REG) {
  1295.                 yyerror("please use MOVEC for control register moves");
  1296.                 break;
  1297.             }
  1298.             w0 |= ($4.r5 >> 3 & 3) << 20 | ($4.r5 & 7) << 16;}
  1299.     |    x_or_y abs_short_addr ',' regs
  1300.             {w0 |= 0x408000 | $1 << 19 | ($2 & 0x3F) << 8;
  1301.             if($4.flags & R_CTL_REG) {
  1302.                 yyerror("please use MOVEC for control register moves");
  1303.                 break;
  1304.             }
  1305.             if($2 > 0x003F && pass == 2)
  1306.                 yyerror("warning: address operand truncated");
  1307.             w0 |= ($4.r5>> 3 & 3) << 20 | ($4.r5 & 7) << 16;}
  1308.     |    regs ',' x_or_y ea
  1309.             {w0 |= 0x404000 | $3 << 19;
  1310.             if($1.flags & R_CTL_REG) {
  1311.                 yyerror("please use MOVEC for control register moves");
  1312.                 break;
  1313.             }
  1314.             w0 |= ($1.r5 >> 3 & 3) << 20 | ($1.r5 & 7) << 16;}
  1315.     |    regs ',' x_or_y abs_short_addr
  1316.             {w0 |= 0x400000 | $3 << 19 | ($4 & 0x3F) << 8;
  1317.             if($1.flags & R_CTL_REG) {
  1318.                 yyerror("please use MOVEC for control register moves");
  1319.                 break;
  1320.             }
  1321.             if($4 > 0x003F && pass == 2)
  1322.                 yyerror("warning: address operand truncated");
  1323.             w0 |= ($1.r5 >> 3 & 3) << 20 | ($1.r5 & 7) << 16;}
  1324.     |    ix_long ',' regs
  1325.             {w0 |= 0x400000 | 0x00F400 | ($3.r5 >> 3 & 3) << 20 |
  1326.                 ($3.r5 & 7) << 16;
  1327.             if($3.flags & R_CTL_REG) {
  1328.                 yyerror("please use MOVEC for control register moves");
  1329.                 break;
  1330.             }
  1331.             uses_w1++; w1 = n2frac($1);
  1332.             }
  1333.     ;
  1334.  
  1335. xr_move    :    x_or_y /* XMEM */ ea ',' regs    regs /* a_b */ ',' YREG
  1336.             {if($1 == 0 && $5.flags & R_AB) {
  1337.                 w0 |= 0x108000 | $4.sdx << 18 | $5.ab << 17 |
  1338.                     $7 << 16;
  1339.             } else {
  1340.                 yyerror("illegal X:R move");
  1341.             }}
  1342.     |     ix ',' regs        regs /* a_b */ ',' YREG
  1343.             {if($4.flags & R_AB) {
  1344.                 w0 |= 0x10B400 | $3.sdx << 18 | $4.ab << 17 |
  1345.                     $6 << 16;
  1346.                 uses_w1++;
  1347.                 w1 |= n2frac($1) & 0xFFFFFF;
  1348.             } else {
  1349.                 yyerror("illegal X:R move");
  1350.             }}
  1351.     |    regs ',' x_or_y /* XMEM */ ea    regs /* a_b */ ',' regs/*YREG*/
  1352.             {if($1.flags & R_SDX && $3 == 0 && $5.flags & R_AB &&
  1353.                 $7.flags & R_YREG) {
  1354.                 w0 |= 0x100000 | $1.sdx << 18 | $5.ab << 17 |
  1355.                     $7.yreg << 16;
  1356.             } else if($1.flags & R_AB && $3 == 0 && 
  1357.                 $5.flags & R_XREG && $7.flags & R_AB) {
  1358.                 if($5.xreg != 0) yyerror("must use X0");
  1359.                 if($1.ab == 0 && $7.ab == 0)
  1360.                     w0 |= 0x080000;
  1361.                 else if($1.ab == 1 && $7.ab == 1)
  1362.                     w0 |= 0x090000;
  1363.                 else
  1364.                     yyerror("illegal X:R move");
  1365.             } else {
  1366.                 yyerror("illegal X:R move");
  1367.             }}
  1368.     ;
  1369.  
  1370. ry_move    :    regs /* a_b */ ',' regs /* XREG    */      YMEM ea ',' regs
  1371.             {if($3.flags & R_XREG && $7.flags & (R_YREG|R_AB)) {
  1372.                 w0 |= 0x10C000 | $1.ab << 19 | $3.xreg << 18 |
  1373.                     $7.sdy << 16;
  1374.             } else {
  1375.                 yyerror("illegal R:Y move");
  1376.             }}
  1377.     |    regs /* a_b */ ',' regs /* XREG    */    ix ',' regs
  1378.             {if($3.flags & R_XREG && $6.flags & (R_YREG|R_AB)) {
  1379.                 w0 |= 0x10F400 | $1.ab << 19 | $3.xreg << 18 |
  1380.                     $6.sdy << 16;
  1381.                 uses_w1++;
  1382.                 w1 |= n2frac($4) & 0xFFFFFF;
  1383.             } else {
  1384.                 yyerror("illegal R:Y move");
  1385.             }}
  1386.     |    regs /* a_b */ ',' regs /* XREG    */    regs ',' YMEM ea
  1387.             {if($1.flags & R_AB && $3.flags & R_XREG) {
  1388.                 w0 |= 0x104000 | $1.ab << 19 | $3.xreg << 18 |
  1389.                 $4.sdy << 16;
  1390.             } else if ($1.flags & R_YREG && $3.flags & R_AB &&
  1391.                 $4.flags & R_AB) {
  1392.                 if($1.yreg != 0) yyerror("must use Y0");
  1393.                 if($3.ab == 0 && $4.ab == 0)
  1394.                     w0 |= 0x088000;
  1395.                 else if($3.ab == 1 && $4.ab == 1)
  1396.                     w0 |= 0x098000;
  1397.                 else
  1398.                     yyerror("illegal R:Y move");
  1399.             } else {
  1400.                 yyerror("illegal R:Y move");
  1401.             }}
  1402.     ;
  1403.  
  1404. l_move    :    LMEM ea ',' regs /* lsd */
  1405.             {if($4.flags & R_CTL_REG) {
  1406.                 yyerror("please use MOVEC for control register moves");
  1407.                 break;
  1408.             }
  1409.             w0 |= 0x40C000 | ($4.lsd & 3) << 16 | ($4.lsd >> 2) << 19;}
  1410.     |    regs /* lsd */ ',' LMEM ea
  1411.             {if($1.flags & R_CTL_REG) {
  1412.                 yyerror("please use MOVEC for control register moves");
  1413.                 break;
  1414.             }
  1415.             w0 |= 0x404000 | ($1.lsd & 3) << 16 | ($1.lsd >> 2) << 19;}
  1416.     |    LMEM abs_short_addr ',' regs /* lsd */
  1417.             {w0 |= 0x408000 | ($4.lsd & 3) << 16 | ($4.lsd >> 2) << 19;
  1418.             if($4.flags & R_CTL_REG) {
  1419.                 yyerror("please use MOVEC for control register moves");
  1420.                 break;
  1421.             }
  1422.             if($2 > 0x003F && pass == 2)
  1423.                 yyerror("warning: address operand truncated");
  1424.             w0 |= ($2 & 0x3F) << 8;}
  1425.     |    regs /* lsd */ ',' LMEM abs_short_addr
  1426.             {w0 |= 0x400000 | ($1.lsd & 3) << 16 | ($1.lsd >> 2) << 19;
  1427.             if($1.flags & R_CTL_REG) {
  1428.                 yyerror("please use MOVEC for control register moves");
  1429.                 break;
  1430.             }
  1431.             if($4 > 0x003F && pass == 2)
  1432.                 yyerror("warning: address operand truncated");
  1433.             w0 |= ($4 & 0x3F) << 8;}
  1434.     ;
  1435.  
  1436. xy_move    :    x_or_y /*XMEM*/ ea /*ea_strange*/ ',' regs    YMEM ea /*ea_strange*/ ',' regs
  1437.             {int eax = $2, eay = $6,
  1438.                  regx = ($4.flags & R_AB) ? $4.ab | 2 : $4.xreg,
  1439.                  regy = ($8.flags & R_AB) ? $8.ab | 2 : $8.yreg;
  1440.             if((eax & 0x400) == (eay & 0x400))
  1441.                 yyerror("registers must be in opposite halves");
  1442.             if(!($4.flags & (R_AB | R_XREG)))
  1443.                 yyerror("invalid X move register");
  1444.             if(!($8.flags & (R_AB | R_YREG)))
  1445.                 yyerror("invalid Y move register");
  1446.             if($4.flags & R_AB &&
  1447.                $8.flags & R_AB &&
  1448.                $4.ab == $8.ab)
  1449.                 yyerror("duplicate destination register");
  1450.             w0 = w0 & 0xFF | 0xC08000;    /* both write */
  1451.             w0 |= eax & 0x1f00 | (eay & 0x300) << 5 | (eay & 0x1800) << 9 | regx << 18 | regy << 16;}
  1452.     |    x_or_y /*XMEM*/ ea /*ea_strange*/ ',' regs    regs ',' YMEM ea /*ea_strange*/
  1453.             {int eax = $2, eay = $8,
  1454.                  regx = ($4.flags & R_AB) ? $4.ab | 2 : $4.xreg,
  1455.                  regy = ($5.flags & R_AB) ? $5.ab | 2 : $5.yreg;
  1456.             if((eax & 0x400) == (eay & 0x400))
  1457.                 yyerror("registers must be in opposite halves");
  1458.             if(!($4.flags & (R_AB | R_XREG)))
  1459.                 yyerror("invalid X move register");
  1460.             if(!($5.flags & (R_AB | R_YREG)))
  1461.                 yyerror("invalid Y move register");
  1462.             w0 = w0 & 0xFF | 0x808000;    /* X:write, Y:read */
  1463.             w0 |= eax & 0x1f00 | (eay & 0x300) << 5 | (eay & 0x1800) << 9 | regx << 18 | regy << 16;}
  1464.     |    regs ',' x_or_y /*XMEM*/ ea /*ea_strange*/    YMEM ea /*ea_strange*/ ',' regs
  1465.             {int eax = $4, eay = $6,
  1466.                  regx = ($1.flags & R_AB) ? $1.ab | 2 : $1.xreg,
  1467.                  regy = ($8.flags & R_AB) ? $8.ab | 2 : $8.yreg;
  1468.             if((eax & 0x400) == (eay & 0x400))
  1469.                 yyerror("registers must be in opposite halves");
  1470.             if(!($1.flags & (R_AB | R_XREG)))
  1471.                 yyerror("invalid X move register");
  1472.             if(!($8.flags & (R_AB | R_YREG)))
  1473.                 yyerror("invalid Y move register");
  1474.                   w0 = w0 & 0xFF | 0xC00000;    /* X:read, Y:write */
  1475.             w0 |= eax & 0x1f00 | (eay & 0x300) << 5 | (eay & 0x1800) << 9 | regx << 18 | regy << 16;}
  1476.     |    regs ',' x_or_y /*XMEM*/ ea /*ea_strange*/    regs ',' YMEM ea /*ea_strange*/
  1477.             {int eax = $4, eay = $8,
  1478.                  regx = ($1.flags & R_AB) ? $1.ab | 2 : $1.xreg,
  1479.                  regy = ($5.flags & R_AB) ? $5.ab | 2 : $5.yreg;
  1480.             if((eax & 0x400) == (eay & 0x400))
  1481.                 yyerror("registers must be in opposite halves");
  1482.             if(!($1.flags & (R_AB | R_XREG)))
  1483.                 yyerror("invalid X move register");
  1484.             if(!($5.flags & (R_AB | R_YREG)))
  1485.                 yyerror("invalid Y move register");
  1486.                   w0 = w0 & 0xFF | 0x800000;    /* both read */
  1487.             w0 |= eax & 0x1f00 | (eay & 0x300) << 5 | (eay & 0x1800) << 9 | regx << 18 | regy << 16;}
  1488.     ;
  1489.  
  1490. /*%%%******* absolute address and immediate data fields ************/
  1491.  
  1492. num    :    CHEX
  1493.             {$$ = $1;}
  1494.     |    CDEC
  1495.             {$$ = $1;}
  1496.     |    FRAC
  1497.             {$$ = $1;}
  1498.     ;
  1499.  
  1500. ix    :    '#' expr
  1501.             {$$ = $2;}
  1502.     |    '#' '<' expr
  1503.             {$$.val.i = n2int($3) & 0xFF;
  1504.             $$.type = INT;
  1505.             long_symbolic_expr = FALSE;}
  1506.     ;
  1507.  
  1508. ix_long    :    '#' '>' expr
  1509.             {$$ = $3;}
  1510.     ;
  1511.  
  1512. abs_addr
  1513.     :    expr
  1514.             {$$ = n2int($1);}
  1515.     |    '*'
  1516.             {$$ = pc;}
  1517.     ;
  1518.  
  1519. abs_short_addr
  1520.     :    '<' expr
  1521.             {$$ = n2int($2);}
  1522.     |    '<' '*'
  1523.             {$$ = pc;}
  1524.     ;
  1525.  
  1526. io_short_addr
  1527.     :    SHL expr
  1528.             {$$ = n2int($2);} 
  1529.     ;
  1530.  
  1531. num_or_sym
  1532.     :    num
  1533.             {$$ = $1;}
  1534.     |    SYM
  1535.             {$$ = sym_ref($1); free($1);}
  1536.     ;
  1537.  
  1538. num_or_sym_expr
  1539.     :    num
  1540.             {$$ = $1;}
  1541.     |    SYM
  1542.             {$$ = sym_ref($1); free($1); long_symbolic_expr++;}
  1543.     |    CHAR
  1544.             {$$.type = INT; $$.val.i = $1 & 0xFFFFFF;}
  1545.     ;
  1546.  
  1547. expr    :    expr '|' expr
  1548.             {$$ = binary_op($1, '|', $3);}
  1549.     |    expr '^' expr
  1550.             {$$ = binary_op($1, '^', $3);}
  1551.     |    expr '&' expr
  1552.             {$$ = binary_op($1, '&', $3);}
  1553.     |    expr SHR expr
  1554.             {$$ = binary_op($1, SHR, $3);}
  1555.     |    expr SHL expr
  1556.             {$$ = binary_op($1, SHL, $3);}
  1557.     |    expr '-' expr
  1558.             {$$ = binary_op($1, '-', $3);}
  1559.     |    expr '+' expr
  1560.             {$$ = binary_op($1, '+', $3);}
  1561.     |    expr '%' expr
  1562.             {$$ = binary_op($1, '%', $3);}
  1563.     |    expr '/' expr
  1564.             {$$ = binary_op($1, '/', $3);}
  1565.     |    expr '*' expr
  1566.             {$$ = binary_op($1, '*', $3);}
  1567.     |    '-' expr %prec '~'
  1568.             {$$ = unary_op('-', $2);}
  1569.     |    '~' expr
  1570.             {$$ = unary_op('~', $2);}
  1571.     |    '(' expr ')'
  1572.             {$$ = $2;}
  1573.     |    num_or_sym_expr
  1574.             {$$ = $1;}
  1575.     ;
  1576.  
  1577. /*%%%****************** end ******************************/
  1578.  
  1579. %%
  1580.  
  1581. #include <stdio.h>
  1582.  
  1583. int yydebug;
  1584.  
  1585. struct n binary_op(a1, op, a2)
  1586. struct n a1, a2;
  1587. int op;
  1588. {
  1589.     struct n result;
  1590.  
  1591.     if(a1.type == UNDEF || a2.type == UNDEF) {
  1592.     result.type = UNDEF;
  1593.     return result;
  1594.     }
  1595.  
  1596.     /* promote to float automatically */
  1597.  
  1598.     if(a1.type != a2.type) {
  1599.     if(a1.type == INT) {
  1600.         a1.val.f = a1.val.i;    /* truncate */
  1601.         a1.type = FLT;
  1602.     } else {
  1603.         a2.val.f = a2.val.i;    /* truncate */
  1604.     }
  1605.     }
  1606.     result.type = a1.type;
  1607.  
  1608.     /* do the op */
  1609.  
  1610.     if(result.type == INT) {
  1611.     switch(op) {
  1612.         case '+':    result.val.i = a1.val.i + a2.val.i; break;
  1613.         case '-':    result.val.i = a1.val.i - a2.val.i; break;
  1614.         case '*':    result.val.i = a1.val.i * a2.val.i; break;
  1615.         case '/':    result.val.i = a1.val.i / a2.val.i; break;
  1616.         case '%':    result.val.i = a1.val.i % a2.val.i; break;
  1617.         case SHL:    result.val.i = a1.val.i << a2.val.i; break;
  1618.         case SHR:    result.val.i = a1.val.i >> a2.val.i; break;
  1619.         case '|':    result.val.i = a1.val.i | a2.val.i; break;
  1620.         case '&':    result.val.i = a1.val.i & a2.val.i; break;
  1621.         case '^':    result.val.i = a1.val.i ^ a2.val.i; break;
  1622.     }
  1623.     } else {
  1624.     switch(op) {
  1625.         case '+':    result.val.f = a1.val.f + a2.val.f; break;
  1626.         case '-':    result.val.f = a1.val.f - a2.val.f; break;
  1627.         case '*':    result.val.f = a1.val.f * a2.val.f; break;
  1628.         case '/':    result.val.f = a1.val.f / a2.val.f; break;
  1629.         case '%':    result.val.f = (int)a1.val.f % (int)a2.val.f; break;
  1630.         case SHL:    result.val.f = (int)a1.val.f << (int)a2.val.f; break;
  1631.         case SHR:    result.val.f = (int)a1.val.f >> (int)a2.val.f; break;
  1632.         case '|':    result.val.f = (int)a1.val.f | (int)a2.val.f; break;
  1633.         case '&':    result.val.f = (int)a1.val.f & (int)a2.val.f; break;
  1634.         case '^':    result.val.f = (int)a1.val.f ^ (int)a2.val.f; break;
  1635.     }
  1636.     }
  1637.  
  1638.     return result;
  1639. }
  1640.  
  1641. struct n unary_op(op, a1)
  1642. int op;
  1643. struct n a1;
  1644. {
  1645.     struct n result;
  1646.  
  1647.     if(a1.type == UNDEF) {
  1648.     result.type = UNDEF;
  1649.     return result;
  1650.     }
  1651.  
  1652.     result.type = a1.type;
  1653.  
  1654.     /* do the op */
  1655.  
  1656.     if(result.type == INT) {
  1657.     switch(op) {
  1658.         case '-':    result.val.i = -a1.val.i; break;
  1659.         case '~':    result.val.i = ~a1.val.i; break;
  1660.     }
  1661.     } else {
  1662.     switch(op) {
  1663.         case '-':    result.val.f = -a1.val.f; break;
  1664.         case '~':    result.val.f = ~(int)a1.val.f; break;
  1665.     }
  1666.     }
  1667.  
  1668.     return result;
  1669. }
  1670.  
  1671. n2int(n)
  1672. struct n n;
  1673. {
  1674.     if(n.type == UNDEF)
  1675.     return UNDEF;
  1676.     else if(n.type == INT)
  1677.     return n.val.i;
  1678.     else
  1679.     return n.val.f;
  1680. }
  1681.  
  1682. n2frac(n)
  1683. struct n n;
  1684. {
  1685.     double adval = n.val.f >= 0.0 ? n.val.f : -n.val.f;
  1686.  
  1687.     if(n.type == UNDEF)
  1688.     return UNDEF;
  1689.     else if(n.type == INT)
  1690.     return n.val.i;
  1691.  
  1692.     adval -= (double)(int)adval;
  1693.     adval *= (double)0x800000;
  1694.     adval += 0.5;
  1695.  
  1696.     if(n.val.f >= 0.0)
  1697.     return adval;
  1698.     else
  1699.     return -adval;
  1700. }
  1701.  
  1702. extern struct {int n; char *name;} tok_tab[];
  1703. extern int n_tok;
  1704.  
  1705. char *tok_print(tok)
  1706. int tok;
  1707. {
  1708.     int i;
  1709.     static char buf[32];
  1710.  
  1711.     if(tok < 256) {
  1712.     sprintf(buf, "'%c'", tok);
  1713.     return(buf);
  1714.     } else {
  1715.     for(i = 0; i < n_tok; i++) {
  1716.         if(tok == tok_tab[i].n)
  1717.         return(tok_tab[i].name);
  1718.     }
  1719.     }
  1720.     return("<unknown>");
  1721. }
  1722.  
  1723. yyerror(s, a0, a1, a2, a3)
  1724. char *s, *a0, *a1, *a2, *a3;
  1725. {
  1726.     extern int error;
  1727.     char buf[1024];
  1728.  
  1729.     error++;
  1730.     sprintf(buf, s, a0, a1, a2, a3);
  1731.  
  1732.     if(pass == 2) {
  1733.     fprintf(stderr, "%s: line %d: %s (tok=%s)\n", curfile, curline,
  1734.         buf, tok_print(yychar));
  1735.     fprintf(stderr, "%s\n", inline); 
  1736.     printf("%s: line %d: %s (tok=%s)\n", curfile, curline,
  1737.         buf, tok_print(yychar));
  1738. #if 0
  1739.     printf("%s\n", inline); 
  1740. #endif
  1741.     }
  1742. }
  1743.  
  1744. char *luntab(s)
  1745. char *s;
  1746. {
  1747.     static char buf[256];
  1748.  
  1749.     strcpy(buf, s);
  1750.  
  1751.     untab(buf);
  1752.     return(buf);
  1753. }
  1754.